home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / nt / source.exe / POSIX / CHOWN / CHOWN.C < prev    next >
C/C++ Source or Header  |  1993-06-23  |  8KB  |  374 lines

  1. /*
  2.  * Copyright (c) 1988 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1988 Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)chown.c    5.18 (Berkeley) 3/9/91";
  42. #endif /* not lint */
  43.  
  44. #ifdef DF_POSIX /* DF_DSC */
  45. #include <misc.h>
  46. #include <bsdlib.h>
  47. #else
  48. #include <sys/param.h>
  49. #endif
  50. #include <sys/types.h>    /* FOR calls to stat */
  51. #include <sys/stat.h>
  52. #include <sys/errno.h>
  53. #include <dirent.h>
  54. #include <fts.h>
  55. #include <pwd.h>
  56. #include <grp.h>
  57. #include <unistd.h>
  58. #include <stdio.h>
  59. #include <ctype.h>
  60. #include <stdlib.h>
  61. #include <string.h>
  62. #if WIN_NT
  63.  
  64. void a_gid __P((register char *));
  65. void a_uid __P((register char *));
  66. void chownerr __P((char *));
  67. void error __P((char *));
  68. void usage __P((void));
  69. void setids __P((char *));
  70.  
  71. extern int globulate __P((int, int, char **));
  72. extern void deglobulate __P((void));
  73. extern int globulated_argc;
  74. extern char **globulated_argv;
  75. pid_t ppid;
  76. int globulation;
  77. #endif
  78.  
  79. int ischown, fflag, rflag, retval;
  80. uid_t uid,t_uid;
  81. gid_t gid,t_gid;
  82. int setid_flg;        /* Flg to do STAT */
  83. char *gname, *myname;
  84.  
  85. int
  86. #if __STDC__
  87. main (int argc, char **argv)
  88. #else
  89. main(argc, argv)
  90.     int argc;
  91.     char **argv;
  92. #endif
  93. {
  94.     extern int optind;
  95.     register FTS *fts;
  96.     register FTSENT *p;
  97.     register char *cp;
  98.     int ch;
  99.  
  100. #if WIN_NT
  101.     ppid = getppid();
  102.     if (ppid == (pid_t) 1) /* if parent is CMD.EXE */
  103.     {
  104.         globulation = globulate(1, argc, argv);
  105.         if (globulation == 0)
  106.         {
  107.             argc = globulated_argc;
  108.             argv = globulated_argv;
  109.         }
  110.     }
  111. #endif
  112.     retval = EXIT_SUCCESS;
  113.     myname = ((cp = rindex(*argv, '/')) != NULL) ? cp + 1 : *argv;
  114.     ischown = myname[2] == 'o';
  115.  
  116.     while ((ch = getopt(argc, argv, "Rf")) != EOF)
  117.         switch((char)ch) {
  118.         case 'R':
  119.             rflag = 1;
  120.             break;
  121.         case 'f':
  122.             fflag = 1;
  123.             break;
  124.         case '?':
  125.         default:
  126.             usage();
  127.         }
  128.     argv += optind;
  129.     argc -= optind;
  130.  
  131.     if (argc < 2)
  132.         usage();
  133.  
  134.     uid = (uid_t)-1;
  135.     gid = (gid_t)-1;
  136.  
  137.     if (ischown) {
  138. #ifdef SUPPORT_DOT
  139.         if (cp = index(*argv, '.')) {
  140.             *cp++ = '\0';
  141.             a_gid(cp);
  142.         } else
  143. #endif
  144.         if ((cp = index(*argv, ':')) != NULL) {
  145.             *cp++ = '\0';
  146.             a_gid(cp);
  147.         } 
  148.         a_uid(*argv);
  149.     }
  150.     else 
  151.         a_gid(*argv);
  152.  
  153. /* Added to take care of retaining grp/usr association if not specified */
  154.     t_uid = uid;
  155.     t_gid = gid;
  156.     setid_flg = ( int ) uid == -1 || ( int ) gid == -1;
  157.  
  158.     if (rflag) {
  159.         if (!(fts = fts_open(++argv, FTS_NOSTAT|FTS_PHYSICAL, 0))) {
  160.             (void)fprintf(stderr,
  161.                 "%s: %s.\n", myname, strerror(errno));
  162. #if WIN_NT
  163.             if (ppid == (pid_t) 1 && globulation == 0)
  164.                 deglobulate();
  165. #endif
  166.             exit(EXIT_FAILURE);
  167.         }
  168.         while ((p = fts_read(fts)) != NULL) {
  169.             if (p->fts_info == FTS_D)
  170.                 continue;
  171.             if (p->fts_info == FTS_ERR) {
  172.                 error(p->fts_path);
  173.                 continue;
  174.             }
  175.             setids(p->fts_accpath);
  176.             if (chown(p->fts_accpath, uid, gid) && !fflag)
  177.                 chownerr(p->fts_path);
  178.         }
  179. #if WIN_NT
  180.         if (ppid == (pid_t) 1 && globulation == 0)
  181.             deglobulate();
  182. #endif
  183.         exit(retval);
  184.     }
  185.  
  186.     while (*++argv) {
  187.         setids(*argv);
  188.         if (chown(*argv, uid, gid) && !fflag)
  189.             chownerr(*argv);
  190.     }
  191. #if WIN_NT
  192.     if (ppid == (pid_t) 1 && globulation == 0)
  193.         deglobulate();
  194. #endif
  195.     return retval;
  196. }
  197.  
  198. void
  199. #if __STDC__
  200. a_gid (register char *s)
  201. #else
  202. a_gid(s)
  203.     register char *s;
  204. #endif
  205. {
  206.     struct group *gr;
  207.  
  208.     if (!*s) {
  209.         gid = (gid_t)-1;    /* argument was "uid." */
  210.         return;
  211.     }
  212.     gname = s;
  213.     if ((gr = getgrnam(s)) != NULL)
  214.         gid = gr->gr_gid;
  215.     else {
  216.         for (; *s && isdigit(*s); ++s);
  217.         if (!*s)
  218.             gid = (gid_t)atoi(gname);
  219.         else {
  220.             (void)fprintf(stderr, "%s: unknown group id: %s\n",
  221.                 myname, gname);
  222. #if WIN_NT
  223.             if (ppid == (pid_t) 1 && globulation == 0)
  224.                 deglobulate();
  225. #endif
  226.             exit(EXIT_FAILURE);
  227.         }
  228.     }
  229. }
  230.  
  231. void
  232. #if __STDC__
  233. a_uid (register char *s)
  234. #else
  235. a_uid(s)
  236.     register char *s;
  237. #endif
  238. {
  239.     struct passwd *pw;
  240.     char *uname;
  241.  
  242.     if (!*s) {
  243.         uid = (uid_t)-1;        /* argument was ".gid" */
  244.         return;
  245.     }
  246.     if ((pw = getpwnam(s)) != NULL)
  247.         uid = pw->pw_uid;
  248.     else {
  249.         for (uname = s; *s && isdigit(*s); ++s);
  250.         if (!*s)
  251.             uid = (uid_t)atoi(uname);
  252.         else {
  253.             (void)fprintf(stderr,
  254.                 "chown: unknown user id: %s\n", uname);
  255. #if WIN_NT
  256.             if (ppid == (pid_t) 1 && globulation == 0)
  257.                 deglobulate();
  258. #endif
  259.             exit(EXIT_FAILURE);
  260.         }
  261.     }
  262. }
  263.  
  264. void
  265. #if __STDC__
  266. chownerr (char *file)
  267. #else
  268. chownerr(file)
  269.     char *file;
  270. #endif
  271. {
  272.     static uid_t euid = (uid_t)-1;
  273.     static int ngroups = -1;
  274.  
  275.     /* check for chown without being root */
  276.     if (errno != EPERM || uid != (uid_t)-1 && euid == (uid_t)-1 && (euid = geteuid()) != 0) {
  277.         if (fflag) {
  278. #if WIN_NT
  279.             if (ppid == (pid_t) 1 && globulation == 0)
  280.                 deglobulate();
  281. #endif
  282.             exit(EXIT_SUCCESS);
  283.         }
  284.         error(file);
  285. #if WIN_NT
  286.         if (ppid == (pid_t) 1 && globulation == 0)
  287.             deglobulate();
  288. #endif
  289.         exit(EXIT_FAILURE);
  290.     }
  291.     /* check group membership; kernel just returns EPERM */
  292.     if (gid != -1 && ngroups == -1) {
  293. #if DF_POSIX /* DF_MSS: NGROUPS_MAX is defined as 0 in Posix headers */
  294. # if NGROUPS_MAX < 1
  295.         gid_t groups[1];
  296. # else
  297.         gid_t groups[NGROUPS_MAX];
  298. # endif
  299. #else
  300.         gid_t groups[NGROUPS_MAX];
  301. #endif
  302.  
  303.         ngroups = getgroups(NGROUPS_MAX, groups);
  304.         while (--ngroups >= 0 && gid != groups[ngroups]);
  305.         if (ngroups < 0) {
  306.             if (fflag) {
  307. #if WIN_NT
  308.                 if (ppid == (pid_t) 1 && globulation == 0)
  309.                     deglobulate();
  310. #endif
  311.                 exit(EXIT_SUCCESS);
  312.             }
  313.             (void)fprintf(stderr,
  314.                 "%s: you are not a member of group %s.\n",
  315.                 myname, gname);
  316. #if WIN_NT
  317.             if (ppid == (pid_t) 1 && globulation == 0)
  318.                 deglobulate();
  319. #endif
  320.             exit(EXIT_FAILURE);
  321.         }
  322.     }
  323.     if (!fflag)
  324.         error(file);
  325. }
  326.  
  327. void
  328. #if __STDC__
  329. error (char *name)
  330. #else
  331. error(name)
  332.     char *name;
  333. #endif
  334. {
  335.     (void)fprintf(stderr, "%s: %s: %s\n", myname, name, strerror(errno));
  336.     retval = EXIT_FAILURE;
  337. }
  338.  
  339. void
  340. #if __STDC__
  341. usage (void)
  342. #else
  343. usage()
  344. #endif
  345. {
  346.     (void)fprintf(stderr, "usage: %s [-Rf] %s file ...\n", myname,
  347.         ischown ? "[owner][:group]" : "group");
  348. #if WIN_NT
  349.     if (ppid == (pid_t) 1 && globulation == 0)
  350.         deglobulate();
  351. #endif
  352.     exit(EXIT_FAILURE);
  353. }
  354.  
  355. void
  356. #if __STDC__
  357. setids (char *fname)
  358. #else
  359. setids ( fname )
  360.     char *fname;
  361. #endif
  362. {
  363.     struct stat buf;
  364.  
  365.     if ( setid_flg )
  366.         if ( stat( fname , &buf ) == 0 )
  367.         {
  368.             if ( t_uid == ( int ) -1 )
  369.                 uid = buf.st_uid;
  370.             if ( t_gid == ( int ) -1 )
  371.                 gid = buf.st_gid;
  372.         }
  373. }
  374.